package site.wanjiahao.client;

import javax.activation.MimetypesFileTypeMap;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Http post请求抽象类，默认为表单数据
 *      具体逻辑就是构造post请求字符串
 */
public abstract class HttpPost extends AbstractHttp {

    // 自定义post请求分隔符
    private static final String boundary = "--------diyhttp124";

    private static final String POST = "POST";

    // 表单响应类型
    private static final String FORM_DATA_CONTEXT_TYPE = "multipart/form-data; boundary=" + boundary;

    private DataOutputStream ds;

    // 普通字段
    protected Map<String, String> textParams = new HashMap<>();

    // 文件字段
    protected Map<String, File> fileParams = new HashMap<>();

    public HttpPost() {
        this.method = POST;
        this.contextType = FORM_DATA_CONTEXT_TYPE;
    }


    // 增加一个普通字符串数据到form表单数据中
    public void addTextParameter(String name, String value) {
        textParams.put(name, value);
    }

    // 增加一个文件到form表单数据中
    public void addFileParameter(String name, File value) {
        fileParams.put(name, value);
    }

    // 构造请求字符串
    protected void writeStringParams() throws Exception {
        if (ds == null) ds = new DataOutputStream(getOutputStream());
        Set<String> keySet = textParams.keySet();
        for (String name : keySet) {
            String value = textParams.get(name);
            ds.writeBytes("--" + boundary + "\r\n");
            ds.writeBytes("Content-Disposition: form-data; name=\"" + name
                    + "\"\r\n");
            ds.writeBytes("\r\n");
            ds.writeBytes(encode(value) + "\r\n");
        }
    }

    // 构造请求字符串
    protected void writeFileParams() throws IOException {
        if (ds == null) ds = new DataOutputStream(getOutputStream());
        Set<String> keySet = fileParams.keySet();
        for (String name : keySet) {
            File value = fileParams.get(name);
            ds.writeBytes("--" + boundary + "\r\n");
            ds.writeBytes("Content-Disposition: form-data; name=\"" + name
                    + "\"; filename=\"" + encode(value.getName()) + "\"\r\n");
            ds.writeBytes("Content-Type: " + new MimetypesFileTypeMap().getContentType(value) + "\r\n");
            ds.writeBytes("\r\n");
            ds.write(getBytes(value));
            ds.writeBytes("\r\n");
        }
    }

    // 构造结束字符串
    protected void paramsEnd() throws IOException {
        if (ds == null) ds = new DataOutputStream(getOutputStream());
        ds.writeBytes("--" + boundary + "--" + "\r\n");
        ds.writeBytes("\r\n");
    }
    
    protected void clearAllParameters() {
        textParams.clear();
        fileParams.clear();
    }

    private byte[] getBytes(File f) throws IOException {
        FileInputStream in = new FileInputStream(f);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int n;
        while ((n = in.read(b)) != -1) {
            out.write(b, 0, n);
        }
        in.close();
        return out.toByteArray();
    }

    private String encode(String value) throws UnsupportedEncodingException {
        return URLEncoder.encode(value, "UTF-8");
    }
}
